home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gwu / predef6.c < prev    next >
C/C++ Source or Header  |  1996-01-30  |  10KB  |  399 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9. /*    +---------------------------------------------------+
  10.       |                                                   |
  11.       |          I N T E R P     P R E D E F S            |
  12.       |            Part 6: Editing Procedures             |
  13.       |                  (C Version)                      |
  14.       |                                                   |
  15.       |   Adapted From Low Level SETL version written by  |
  16.       |                                                   |
  17.       |                  Monte Zweben                     |
  18.       |               Philippe Kruchten                   |
  19.       |               Jean-Pierre Rosen                   |
  20.       |                                                   |
  21.       |    Original High Level SETL version written by    |
  22.       |                                                   |
  23.       |                   Clint Goss                      |
  24.       |               Tracey M. Siesser                   |
  25.       |               Bernard D. Banner                   |
  26.       |               Stephen C. Bryant                   |
  27.       |                  Gerry Fisher                     |
  28.       |                                                   |
  29.       |              C version written by                 |
  30.       |                                                   |
  31.       |               Robert B. K. Dewar                  |
  32.       |                                                   |
  33.       +---------------------------------------------------+
  34. */
  35.  
  36. /* This module contains routines for the implementation of some of
  37.  * the predefined Ada packages and routines, namely SEQUENTIAL_IO,
  38.  * DIRECT_IO, TEXT_IO, and CALENDAR. Part 6 contains the routines
  39.  * for generating string images of internal objects.
  40. */
  41.  
  42. #include <math.h>
  43. #include "ipredef.h"
  44.  
  45. static double image_real_digits (double, int, char *);
  46. static void image_real (double, int, int, int);
  47.  
  48. /* IMAGE_REAL_DIGITS */
  49.  
  50. /* Procedure to output number of digits specified by multiplying dval, which
  51.  * is non-negative and less than 1.0, successively by 10. Output digits are
  52.  * placed in string s. The value returned is the reduced value of dval. For
  53.  * example, if dval is 0.314689 on entry, and n is 3, then the characters 314
  54.  * are output, and the returned value is 0.689
  55. */
  56.  
  57. static double image_real_digits (double dval, int n, char *s)
  58.                                                         /*;image_real_digits*/
  59. {
  60.     int     i;
  61.  
  62.     while (n--) {
  63.         dval *= 10.0;
  64.         i = (int)floor(dval);
  65.         *s++ = '0' + i;
  66.         dval = dval - (double)i;
  67.     }
  68.     return dval;
  69. }
  70.  
  71.  
  72. /* IMAGE_REAL */
  73.  
  74. /* This routine is shared for fixed and float values. It returns a string image
  75.  * of the double value dval, using fore, aft, exp as described in 14.3.8. The
  76.  * resulting string image is stored in work_string. Note: if fore is zero, then
  77.  * the string has the minimum required number of characters before the point.
  78.  * If an out of range value is encountered, the exception in data_exception
  79.  * is raised. If a bad character is encountered, DATA_ERROR is raised.
  80. */
  81.  
  82. static void image_real (double dval, int fore, int aft, int exp) /*;image_real*/
  83. {
  84.     int     exponent;
  85.     char    sign;
  86.     char    *s, *t;
  87.     int     total_digits;
  88.     int     exp_digits;
  89.     double  round;
  90.  
  91.     /* Set pointer s to generate output characters in work string */
  92.  
  93.     s = work_string;
  94.  
  95.     /* Make sure fore, aft, exp have acceptable values. 14.3.7 does not
  96.      * justify limiting fore, aft and exp to 512, but it seems reasonable!
  97.     */
  98.  
  99.     if (fore <= 0) fore = 1;
  100.     else if (fore > 512) fore = 512;
  101.  
  102.     if (aft < 0) aft = 0;
  103.     else if (aft > 512) aft = 512;
  104.  
  105.     if (exp < 0) exp = 0;
  106.     else if (exp > 512) exp = 512;
  107.  
  108.     /* Deal with 0.0 specially */
  109.  
  110.     if (dval == 0.0) {
  111.         while (fore-- > 1) *s++ = ' ';
  112.         *s++ = '0';
  113.         *s++ = '.';
  114.  
  115.         while (aft--) *s++ = '0';
  116.  
  117.         if (exp) {
  118.             *s++ = 'E';
  119.             *s++ = '+';
  120.             exp--;
  121.             exp = MAX(exp,1);
  122.  
  123.             while (exp--) *s++ = '0';
  124.         }
  125.         *s = 0;
  126.         return;
  127.     }
  128.  
  129.     /* If non-zero capture sign */
  130.  
  131.     if (dval < 0.0) {
  132.         sign = '-';
  133.         dval = -dval;
  134.         fore--;
  135.     }
  136.     else sign = '+';
  137.  
  138.     /* Reduce number to range 0.1 <= dval < 1.0, except that we do not
  139.      * scale up if there is no exponent field, since we are happy with
  140.      * leading zeroes in this case
  141.     */
  142.  
  143.     exponent = 0;
  144.     if (exp != 0) {
  145.         while (dval < 0.1) {
  146.             exponent--;
  147.             dval *= 10.0;
  148.         }
  149.     }
  150.  
  151.     while (dval >= 1.0) {
  152.         exponent++;
  153.         dval /= 10.0;
  154.     }
  155.  
  156.     /* A special case, if there is no exponent field, we want at least one
  157.      * digit in front of the point, which means that the exponent value
  158.      * should be at least one to get the proper value for this digit.
  159.     */
  160.  
  161.     if (exp == 0 && exponent == 0) {
  162.         exponent++;
  163.         dval /= 10.0;
  164.     }
  165.  
  166.     /* To round up, we must add a 5 in the place one past the last one to
  167.      * be displayed. For the case of no exponent field there are exponent
  168.      * digits before the point, otherwise there is only one digit. Note
  169.      * that it is possible for rounding to push us back over 1.0
  170.     */
  171.  
  172.     if (exp == 0) total_digits = aft + exponent;
  173.     else total_digits = aft + 1;
  174.  
  175.     round = 0.5;
  176.     while (total_digits--) round /= 10.0;
  177.  
  178.     dval += round;
  179.  
  180.     if (dval >= 1.0) {
  181.         dval /= 10.0;
  182.         exponent++;
  183.     }
  184.  
  185.     /* Convert number for case of no exponent field present */
  186.  
  187.     if (exp == 0) {
  188.         while (fore > exponent) {
  189.             fore--;
  190.             *s++ = ' ';
  191.         }
  192.  
  193.         if (sign == '-') *s++ = sign;
  194.  
  195.         dval = image_real_digits(dval,exponent,s);
  196.         s += exponent;
  197.         *s++ = '.';
  198.         image_real_digits(dval,aft,s);
  199.         s += aft;
  200.     }
  201.  
  202.     /* Convert number for case of exponent present */
  203.  
  204.     else {
  205.         while (fore > 1) {
  206.             fore--;
  207.             *s++ = ' ';
  208.         }
  209.  
  210.         if (sign == '-') *s++ = sign;
  211.  
  212.         dval = image_real_digits(dval,1,s);
  213.         s++;
  214.         *s++ = '.';
  215.         image_real_digits(dval,aft,s);
  216.         s += aft;
  217.  
  218.         /* Convert the exponent, first output E and sign */
  219.  
  220.         exponent--;          /* since one digit before point */
  221.         *s++ = 'E';
  222.         if (exponent < 0) {
  223.             exponent = -exponent;
  224.             *s++ = '-';
  225.         }
  226.         else *s++ = '+';
  227.         exp--;               /* to account for sign */
  228.         if (exp == 0) exp=1; /* but leave at least one digit */
  229.  
  230.         /* Output digits of exponent */
  231.  
  232.         t = s + 64;          /* cannot be more than 64 non-zero dec digits! */
  233.         exp_digits = 0;
  234.         while (exponent) {
  235.             exp_digits++;
  236.             *--t = '0' + (exponent % 10);
  237.             exponent /= 10;
  238.         }
  239.  
  240.         while (exp-- > exp_digits) *s++ = '0';
  241.         while (exp_digits--) *s++ = *t++;
  242.     }
  243.  
  244.     /* Conversion is complete */
  245.  
  246.     *s = 0;
  247. }
  248.  
  249.  
  250. /* IMAGE_INTEGER */
  251.  
  252. /* Returns a string image of item using the given base in work_string. If
  253.  * an out of range value is encountered, the exception in data_exception
  254.  * is raised. If a bad character is encountered, DATA_ERROR is raised.
  255. */
  256.  
  257. void image_integer(int item, int base)               /*;image_integer*/
  258. {
  259.     char    *p, *q;
  260.     int     digit;
  261.  
  262.     /* Convert base if not 10 */
  263.  
  264.     p = work_string;
  265.     if (base != 10) {
  266.         if (base > 10) {
  267.             *p++ = '1';
  268.             *p++ = '0' + base - 10;
  269.         }
  270.         else *p++ = base + '0';
  271.         *p++ = '#';
  272.     }
  273.  
  274.     /* Deal with sign. Note: we work with the negative of the absolute
  275.      * value of the number so that we do not have to make special checks
  276.      * for the largest negative number in the twos complement case.
  277.     */
  278.  
  279.     if (item < 0) *p++ = '-';
  280.     else item = -item;
  281.  
  282.     /* Convert value to digit string in specified base */
  283.  
  284.     if (item == 0) {
  285.         *p++ = '0';
  286.     }
  287.     else {
  288.         q = work_string + 15;
  289.         *q = 0;
  290.         while(item) {
  291.             digit = -(item % base);
  292.             item /= base;
  293.             *--q = (digit > 9) ? digit - 10 + 'A' : digit + '0';
  294.         }
  295.         while(*p++ = *q++);
  296.         p--;
  297.     }
  298.  
  299.     /* Add final # if based, and we are done */
  300.  
  301.     if (base != 10) *p++ = '#';
  302.     *p = 0;
  303. }
  304.  
  305.  
  306. /* IMAGE_FIXED */
  307.  
  308. /* Returns a string image of the fixed point value item_val, where item_type
  309.  * is a pointer to the type template, and fore, aft and exp control the
  310.  * format according to the rules in 14.3.8. The result is in work_string.
  311.  * Note: if fore is zero, then the result string has the minimum required
  312.  * number of characters before the point. If an out of range value is
  313.  * encountered, the exception in data_exception is raised. If a bad character
  314.  * is encountered, DATA_ERROR is raised.
  315. */
  316.  
  317. void image_fixed (long item_val, int *item_type, int fore, int aft, int exp)
  318.                                                             /*;image_fixed*/
  319. {
  320.     int     exp2, exp5;
  321.     double  dval;
  322.  
  323.     exp2 = FX_RANGE(item_type)->small_exp_2;
  324.     exp5 = FX_RANGE(item_type)->small_exp_5;
  325.  
  326.     dval = (double)item_val;
  327.  
  328.     while (exp2 > 0) {
  329.         exp2--; 
  330.         dval *= 2.0;
  331.     }
  332.     while (exp2 < 0) {
  333.         exp2++; 
  334.         dval /= 2.0;
  335.     }
  336.     while (exp5 > 0) {
  337.         exp5--; 
  338.         dval *= 5.0;
  339.     }
  340.     while (exp5 < 0) {
  341.         exp5++; 
  342.         dval /= 5.0;
  343.     }
  344.  
  345.     image_real (dval,fore,aft,exp);
  346. }
  347.  
  348.  
  349. /* IMAGE_FLOAT */
  350.  
  351. /* Returns a string image of the float value item_val, where fore, aft and
  352.  * exp control the format according to the rules in 143.8. The result is in
  353.  * work_string. Note: if fore is zero, then the result string has the minimum
  354.  * required number of characters before the point. If an out of range value is
  355.  * encountered, the exception in data_exception is raised. If a bad character
  356.  * is encountered, DATA_ERROR is raised.
  357. */
  358.  
  359. void image_float (float num, int fore, int aft, int exp)        /*;image_float*/
  360. {
  361.     image_real ((double)(num),fore,aft,exp);
  362. }
  363.  
  364.  
  365. /* IMAGE_ENUM */
  366.  
  367. /* Procedure to return the value of the given enumeration type value as a
  368.  * string in work_string. The type_ptr parameter points to the type or
  369.  * subtype template to be used for the operation.
  370.  */
  371.  
  372. void image_enum(int enum_val, int *type_ptr)                  /*;image_enum*/
  373. {
  374.     int     *ptr;
  375.     char    *c;
  376.     int     lit_len;
  377.  
  378.     if (TYPE(type_ptr) == TT_E_RANGE)    /* an actual subtype */
  379.         type_ptr = ADDR(E_RANGE(type_ptr) -> ebase, E_RANGE(type_ptr) -> eoff);
  380.  
  381.     enum_val -= E_RANGE(type_ptr) -> elow;
  382.     ptr = type_ptr + WORDS_E_RANGE;/* names are just past template */
  383.     lit_len = *ptr++;
  384.     c = work_string;
  385.     if (lit_len == -1) { /* special case for character */
  386.         *c++ = QUOTE;
  387.         *c++ = enum_val;
  388.         *c++ = QUOTE;
  389.     }
  390.     else {
  391.         while(enum_val--) {
  392.             ptr += lit_len;
  393.             lit_len = *ptr++;
  394.         }
  395.         while(lit_len--) *c++ = *ptr++;
  396.     }
  397.     *c = 0;
  398. }
  399.